using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Management;

namespace RollManager.Library.Utils
{
    public class Common
    {
        private static int s_userId = -1;
        private static string s_psToolsDir = null;

        public static string PsToolsDir
        {
            get
            {
                if( s_psToolsDir == null )
                {
                    s_psToolsDir = AppDomain.CurrentDomain.BaseDirectory;
                    s_psToolsDir = Path.Combine( s_psToolsDir, "PsTools" );
                }
                return s_psToolsDir;
            }
        }

        public static int UserId
        {
            get
            {
                if( s_userId == -1 )
                {
                    s_userId = Database.GetUserId( UserName );
                }
                return s_userId;
            }
        }

        public static string UserName
        {
            get
            {
                return Environment.UserName;
            }
        }

        public static List<DirectoryInfo> ListDirectories(string rootDir, string filter, SearchOption option)
        {
            DirectoryInfo dir = new DirectoryInfo( rootDir );
            List<DirectoryInfo> subDirs = new List<DirectoryInfo>( dir.GetDirectories( filter, option ) );
            subDirs.Sort( delegate( DirectoryInfo dirA, DirectoryInfo dirB )
                              {
                                  return dirB.CreationTime.CompareTo(dirA.CreationTime);
                              } );

            return subDirs;
        }

        public static void RunCommand(string command, string args, ProgressReporter progress)
        {
            // setup process to run log parser
            ProcessStartInfo startInfo = new ProcessStartInfo( command, args );

            // setup process options
            startInfo.CreateNoWindow = true;
            startInfo.UseShellExecute = false;
            startInfo.RedirectStandardOutput = true;
            //startInfo.RedirectStandardError = true;

            // start process
            Process process = new Process();
            process.StartInfo = startInfo;

            process.OutputDataReceived += delegate( object sender, DataReceivedEventArgs e )
            {
                if( !string.IsNullOrEmpty( e.Data ) )
                {
                    progress.Add( e.Data );
                }
            };

            //process.ErrorDataReceived += delegate( object sender, DataReceivedEventArgs e )
            //{
            //    if( !string.IsNullOrEmpty( e.Data ) )
            //    {
            //        progress.Add( e.Data );
            //    }
            //};

            process.Start();
            process.BeginOutputReadLine();
            //process.BeginErrorReadLine();
            process.WaitForExit();
            process.Close();
        }

        public static ManagementObject GetService( string server, string serviceName )
        {
            return GetWmiObject( @"\\{0}\root\cimv2", server, "Win32_Service", serviceName );
        }

        private static ManagementScope GetWmiScope( string path, string server )
        {
            ManagementScope scope = new ManagementScope( string.Format( path, server ) );
            scope.Options.Authentication = AuthenticationLevel.PacketPrivacy;
            scope.Options.EnablePrivileges = true;
            scope.Options.Impersonation = ImpersonationLevel.Impersonate;
            scope.Connect();

            return scope;
        }

        public static ManagementClass GetWmiClass( string path, string server, string theClass )
        {
            return new ManagementClass( GetWmiScope( path, server ), new ManagementPath( theClass ),
                new ObjectGetOptions( null, new TimeSpan( 0, 0, 1, 0, 0 ), true ) );
        }

        public static ManagementObject GetWmiObject(string path, string server, string query)
        {
            //obj.Options = new ObjectGetOptions( null, new TimeSpan( 0, 0, 1, 0, 0 ), true );

            ManagementObjectSearcher searcher = new ManagementObjectSearcher(
                GetWmiScope( path, server ),new ObjectQuery(query));

            ManagementObjectCollection.ManagementObjectEnumerator iter = searcher.Get().GetEnumerator();
            if( !iter.MoveNext() )
            {
                throw new Exception( string.Format( "Could not find {0} on {1}.", query, server ) );
            }

            return (ManagementObject) iter.Current;
        }

        public static ManagementObject GetWmiObject( string path, string server, string theClass, string objName )
        {
            theClass = string.Format( "{0}.Name=\"{1}\"", theClass, objName );

            ManagementObject obj = new ManagementObject( GetWmiScope( path, server ), new ManagementPath( theClass ),
                new ObjectGetOptions( null, new TimeSpan( 0, 0, 1, 0, 0 ), true ) );

            // Make sure the object is valid.
            try
            {
                ManagementPath objPath = obj.ClassPath;
            }
            catch( ManagementException )
            {
                throw new Exception(
                    string.Format( "Could not find {0} on {1}.", objName, server ) );
            }

            return obj;
        }
    }
}
